package com.gcloud.controller.storage.dao;

import com.gcloud.common.util.StringUtils;
import com.gcloud.controller.storage.entity.DiskCategory;
import com.gcloud.controller.storage.entity.StoragePool;
import com.gcloud.controller.storage.model.DescribeDiskCategoriesParams;
import com.gcloud.controller.storage.model.DetailDiskCategoryParams;
import com.gcloud.core.exception.GCloudException;
import com.gcloud.framework.db.PageResult;
import com.gcloud.framework.db.dao.impl.JdbcBaseDaoImpl;
import com.gcloud.header.compute.enums.ComputeNodeState;
import com.gcloud.header.compute.enums.StorageType;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;
/**
Copyright (c) [2020] [G-CLOUD TECHNOLOGY] [G-Cloud 8.0] is licensed under the Mulan PSL v1.
You can use this software according to the terms and conditions of the Mulan PSL v1. You may obtain
a copy of Mulan PSL v1 at: http://license.coscl.org.cn/MulanPSL THIS SOFTWARE IS PROVIDED ON AN 
"AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v1 for more details.
 */
@Repository
public class DiskCategoryDao extends JdbcBaseDaoImpl<DiskCategory, String> {
	public <E> List<E> detailDiskCategory(DetailDiskCategoryParams params, Class<E> clazz) {
		StringBuffer sql = new StringBuffer();
		List<Object> values = new ArrayList<>();
		
//		sql.append("select c.*, zone.id as zone_id, zone.name as zone_name, "
//				+ "pool.id as pool_id, pool.display_name as pool_name "
//				+ "from gc_disk_categories as c "
//				+ "left join gc_disk_category_pools as cp on c.id = cp.disk_category_id "
//				+ "left join gc_zones as zone on cp.zone_id = zone.id "
//				+ "left join gc_storage_pools as pool on cp.storage_pool_id = pool.id "
//				+ "where c.id = ?");
		sql.append("select dc.*, zdc.zone_id as zone_id, zone.name as zone_name, pool.id as pool_id, pool.pool_name as pool_name, pool.hostname as hostname ");
		sql.append(" from gc_disk_categories as dc ");
		sql.append(" left join gc_zone_disk_categories as zdc on dc.id = zdc.disk_category_id ");
		sql.append(" left join gc_disk_category_pools as dcp on zdc.disk_category_id = dcp.disk_category_id and zdc.zone_id = dcp.zone_id ");
		sql.append(" left join gc_zones as zone on zdc.zone_id = zone.id ");
		sql.append(" left join gc_storage_pools as pool on dcp.storage_pool_id = pool.id ");
		sql.append(" where dc.id = ?");
		values.add(params.getDiskCategoryId());
		
		return findBySql(sql.toString(), values, clazz);
	}
	
    public <E> List<E> diskCategoryList(String zoneId, Class<E> clazz){

        StringBuffer sql = new StringBuffer();
        //TODO 有可能会重复
        sql.append("select * from gc_disk_categories c where c.id in");
        sql.append(" (select p.disk_category_id p from gc_disk_category_pools p where p.zone_id = ?)");

        List<Object> values = new ArrayList<>();
        values.add(zoneId);

        return findBySql(sql.toString(), values, clazz);
    }
    
    public <E> PageResult<E> describeDiskCategories(DescribeDiskCategoriesParams params, Class<E> clazz) {
    	StringBuffer sql = new StringBuffer();
    	List<Object> values = new ArrayList<>();
    	
//    	sql.append("select c.*, zone.id as zone_id, zone.name as zone_name, "
//				+ "pool.id as pool_id, pool.display_name as pool_name "
//				+ "from gc_disk_categories as c "
//				+ "left join gc_disk_category_pools as cp on c.id = cp.disk_category_id "
//				+ "left join gc_zones as zone on cp.zone_id = zone.id "
//				+ "left join gc_storage_pools as pool on cp.storage_pool_id = pool.id "
//				+ "where 1 = 1 ");
    	
    	sql.append("select c.* from gc_disk_categories as c");
    	sql.append(" where 1 = 1 ");
    	
    	if(StringUtils.isNotBlank(params.getDiskCategoryName())) {
    		sql.append(" and c.name like concat('%', ?, '%') ");
    		values.add(params.getDiskCategoryName());
    	}
		String zoneId = StringUtils.isNotBlank(params.getZoneId()) ? params.getZoneId() : params.getAvailableForHostZone();
		if(StringUtils.isNotBlank(zoneId)) {
    		sql.append(" and c.id in(select dcp.disk_category_id from gc_disk_category_pools as dcp where dcp.zone_id = ?)");    		
    		values.add(zoneId);
    	}
    	
    	if(StringUtils.isNotBlank(params.getStorageType())) {
    		StorageType type = StorageType.value(params.getStorageType());
    		if(null == type) {
    			throw new GCloudException("::无法识别存储类型");
    		}
    		sql.append(" and c.storage_type = ? ");
    		values.add(type.getValue());
    	}
    	
    	if(StringUtils.isNotBlank(params.getHostname())) {
    		sql.append(" and c.id in (");
    		sql.append(" select dcp.disk_category_id from gc_disk_category_pools dcp where dcp.hostname = ? ");
    		sql.append(")");
    		values.add(params.getHostname());
    	}

    	if(StringUtils.isNotBlank(params.getAvailableForHost())){
			sql.append(" and c.id in (");
			sql.append(" select dcp.disk_category_id from gc_disk_category_pools dcp where (dcp.hostname = ? and dcp.storage_type = ?) or dcp.storage_type != ?");
			sql.append(")");
			values.add(params.getAvailableForHost());
			values.add(StorageType.LOCAL.getValue());
			values.add(StorageType.LOCAL.getValue());
		}
    	
    	return findBySql(sql.toString(), values, params.getPageNumber(), params.getPageSize(), clazz);
    }

    public List<String> diskCategoryHost(String id, String zoneId, Boolean alive){
		StringBuffer sql = new StringBuffer();
		List<Object> values = new ArrayList<>();

		sql.append("select distinct p.hostname from gc_disk_category_pools cp, gc_storage_pools p where cp.storage_pool_id = p.id");
		sql.append(" and cp.disk_category_id = ? and cp.zone_id = ?");
		values.add(id);
		values.add(zoneId);

		if(alive != null){
			sql.append(" and (p.hostname is null  or p.hostname in (select n.hostname from gc_compute_nodes n where n.state = ?))");
			values.add(alive ? ComputeNodeState.CONNECTED.getValue() : ComputeNodeState.DISCONNECTED.getValue());
		}

		return this.jdbcTemplate.queryForList(sql.toString(), values.toArray(), String.class);
	}

	public StoragePool diskCategoryStoragePool(String id, String zoneId, String hostname, Boolean alive){
		StringBuffer sql = new StringBuffer();
		List<Object> values = new ArrayList<>();

		sql.append("select p.* from gc_disk_category_pools cp, gc_storage_pools p where cp.storage_pool_id = p.id");
		sql.append(" and cp.disk_category_id = ? and cp.zone_id = ?");
		values.add(id);
		values.add(zoneId);

		if(StringUtils.isNotBlank(hostname)){
			sql.append(" and p.hostname = ?");
			values.add(hostname);
		}

		sql.append(" limit 1");

		List<StoragePool> storagePools = this.findBySql(sql.toString(), values, StoragePool.class);
		if(storagePools != null && storagePools.size() > 0){
			return storagePools.get(0);
		}
		return null;
	}

	public List<String> diskCategoryStorageType(){
		StringBuffer sql = new StringBuffer();
		sql.append("select distinct t.storage_type from gc_disk_categories t order by t.storage_type;");

		return this.jdbcTemplate.queryForList(sql.toString(), String.class);
	}

}